package com.feng.cloud.system.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.feng.cloud.common.constants.SystemConstant;
import com.feng.cloud.common.exception.AuthException;
import com.feng.cloud.common.exception.auth.AuthStatus;
import com.feng.cloud.common.exception.system.ParameterException;
import com.feng.cloud.common.exception.system.SystemStatus;
import com.feng.cloud.common.request.QueryRequest;
import com.feng.cloud.common.utils.LambdaUtils;
import com.feng.cloud.common.utils.SortUtils;
import com.feng.cloud.system.entity.SystemUser;
import com.feng.cloud.system.entity.UserRole;
import com.feng.cloud.system.mapper.UserMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;

/**
 * @ClassName UserService
 * @Description TODO
 * @Author Better Feng
 * @Date 2019/12/19 17:40
 * @Version 1.0
 **/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
@AllArgsConstructor
@Slf4j
public class UserService extends ServiceImpl<UserMapper, SystemUser> {

    private final LoginLogService loginLogService;
    private final PasswordEncoder passwordEncoder;
    private final UserMapper userMapper;
    private final UserRoleService userRoleService;

    @Override
    @Transactional
    public boolean save(SystemUser user) {
        // 创建用户
        user.setCreateTime(LocalDateTime.now());
        user.setAvatar(SystemUser.DEFAULT_AVATAR);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        boolean save = super.save(user);
        // 保存用户角色
        String[] roles = user.getRoleId().split(StringPool.COMMA);
        setUserRoles(user, roles);
        return save;
    }

    private void setUserRoles(SystemUser user, String[] roles) {
        List<UserRole> userRoles = new ArrayList<>();
        Arrays.stream(roles).forEach(roleId -> {
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getUserId());
            userRole.setRoleId(Long.valueOf(roleId));
            userRoles.add(userRole);
        });
        userRoleService.saveBatch(userRoles);
    }

    @Transactional
    public void updateLoginTime(String username) {
        if (StringUtils.isBlank(username)) {
            throw new ParameterException(SystemStatus.USERNAME_EMPTY);
        }
        SystemUser user = new SystemUser();
        user.setLastLoginTime(LocalDateTime.now());
        this.baseMapper.update(user, new LambdaQueryWrapper<SystemUser>().eq(SystemUser::getUsername, username));
    }

    public SystemUser selectUserByName(String name) {
        if (StringUtils.isBlank(name)) {
            throw new ParameterException(SystemStatus.USERNAME_EMPTY);
        }
        Map<String, Object> map = new HashMap<>(1);
        map.put(LambdaUtils.getProperty(SystemUser::getUsername), name);
        Page<SystemUser> page = new Page<>(1,1,false);
        IPage<SystemUser> iPage = userMapper.selectListByPage(page, map);
        List<SystemUser> userList = iPage.getRecords();
        if (CollectionUtils.isEmpty(userList)) {
            return null;
        }
        return userList.get(0);
    }

    public Map<String, Object> indexData(String username) {
        Map<String, Object> data = new HashMap<>();
        // 获取系统访问记录
        Long totalVisitCount = loginLogService.findTotalVisitCount();
        data.put("totalVisitCount", totalVisitCount);
        Long todayVisitCount = loginLogService.findTodayVisitCount();
        data.put("todayVisitCount", todayVisitCount);
        Long todayIp = loginLogService.findTodayIp();
        data.put("todayIp", todayIp);
        // 获取近期系统访问记录
        List<Map<String, Object>> lastTenVisitCount = loginLogService.findLastTenDaysVisitCount(null);
        data.put("lastTenVisitCount", lastTenVisitCount);
        SystemUser param = new SystemUser();
        param.setUsername(username);
        List<Map<String, Object>> lastTenUserVisitCount = loginLogService.findLastTenDaysVisitCount(param);
        data.put("lastTenUserVisitCount", lastTenUserVisitCount);
        return data;
    }

    @Transactional
    public int updateUserProfileById(SystemUser user) {
        user.setPassword(null);
        user.setUsername(null);
        user.setStatus(null);
        // 根据 ID 选择修改
        user.setModifyTime(LocalDateTime.now());
        return this.baseMapper.updateById(user);
    }

    /**
     *
     * @param username 用户名
     * @param password 密码
     * @return SystemUser
     */
    public SystemUser checkUserByUsernameAndPassword(String username, String password) {
        SystemUser systemUser = selectUserByName(username);
        if (systemUser != null) {
            if (StringUtils.isNotBlank(password)) {
                // 校验密码
                boolean matches = passwordEncoder.matches(password, systemUser.getPassword());
                if (!matches) {
                    return null;
                }
            }
        }
        return systemUser;
    }

    /**
     * 修改密码
     * @param username 用户名
     * @param password 密码
     * @param newPassword 新密码
     */
    public void updatePassword(String username, String password, String newPassword) {
        // 校验要修改的用户名和密码
        SystemUser systemUser = checkUserByUsernameAndPassword(username, password);
        if (systemUser == null) {
            throw new AuthException(AuthStatus.USERNAME_OR_PASSWORD_ERROR);
        }
        // 修改密码
        systemUser.setPassword(passwordEncoder.encode(newPassword));
        systemUser.setModifyTime(LocalDateTime.now());
        this.baseMapper.updateById(systemUser);
    }

    /**
     * 列表查询
     * @param request QueryRequest
     * @return IPage
     */
    public IPage<SystemUser> selectListByPage(QueryRequest request) {
        // 分页
        Page<SystemUser> page = new Page<>();
        SortUtils.handlePageAndSort(request,page,SystemUser::getUserId, SystemConstant.ORDER_DESC,false);
        return userMapper.selectListByPage(page, request);
    }

    /**
     * 更新用户
     * @param user SystemUser
     */
    @Transactional
    public void updateUser(SystemUser user) {
        // 更新用户
        user.setPassword(null);
        user.setUsername(null);
        user.setCreateTime(null);
        user.setModifyTime(LocalDateTime.now());
        this.baseMapper.updateById(user);

        userRoleService.remove(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, user.getUserId()));
        String[] roles = user.getRoleId().split(StringPool.COMMA);
        setUserRoles(user, roles);
    }

    /**
     * 删除用户
     * @param userIds ids
     */
    @Transactional
    public void deleteUsers(String[] userIds) {
        List<String> list = Arrays.asList(userIds);
        removeByIds(list);
        // 删除用户角色
        this.userRoleService.deleteUserRolesByUserId(userIds);
    }

    public void resetPassword(String[] usernameArr) {
        SystemUser params = new SystemUser();
        params.setPassword(passwordEncoder.encode(SystemUser.DEFAULT_PASSWORD));

        List<String> list = Arrays.asList(usernameArr);
        this.baseMapper.update(params, new LambdaQueryWrapper<SystemUser>().in(SystemUser::getUsername, list));
    }
}

